const db = require("../db/mysql");
const fs = require('fs');
const path = require('path');
const { v4: uuidv4 } = require('uuid');
const mime = require('mime-types');
const sharp = require('sharp'); // 用于生成缩略图
const { promisify } = require('util');

// 将fs方法转换为Promise形式
const renameAsync = promisify(fs.rename);
const mkdirAsync = promisify(fs.mkdir);
const existsAsync = promisify(fs.exists);
const unlinkAsync = promisify(fs.unlink);

// 文件大小限制
const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
const MAX_TOTAL_SIZE = 500 * 1024 * 1024; // 500MB

/**
 * 生成缩略图
 * @param {string} sourcePath - 源文件路径
 * @param {string} targetPath - 缩略图路径
 * @param {number} width - 缩略图宽度
 * @param {number} height - 缩略图高度
 */
async function generateThumbnail(sourcePath, targetPath, width = 200, height = 200) {
    try {
        await sharp(sourcePath)
            .resize(width, height)
            .toFile(targetPath);
        return true;
    } catch (error) {
        console.error('缩略图生成失败:', error);
        return false;
    }
}

/**
 * 上传文件并存入数据库（完整字段填充）
 * @param {Object} ctx - Koa上下文
 * @returns {Object} 包含文件列表的响应
 */
const uploadFile = async (ctx) => {
    // 1. 验证基本参数
    if (!ctx.request.files || Object.keys(ctx.request.files).length === 0) {
        ctx.status = 400;
        ctx.body = { code: 400, message: '请上传文件' };
        return;
    }
    const userid = ctx.tokenObj.id
    console.log(userid);
    // ctx.request.body.userid
    // 调试日志：打印整个请求体结构
    console.log('Request body:', ctx.request.body);

    // 尝试从不同位置获取字段（兼容不同版本的 koa-body）
    const { description } = ctx.request.body || ctx.request.fields || {};
    if (!userid) {
        ctx.status = 400;
        ctx.body = { code: 400, message: '用户ID不能为空' };
        return;
    }

    try {
        // 2. 准备文件存储目录（按年月分类）
        const now = new Date();
        const dateFolder = `${now.getFullYear()}/${String(now.getMonth() + 1).padStart(2, '0')}`;
        const uploadDir = path.join(__dirname, '../uploads', dateFolder);
        const thumbnailDir = path.join(__dirname, '../thumbnails', dateFolder);

        // 创建目录（如果不存在）
        if (!await existsAsync(uploadDir)) {
            await mkdirAsync(uploadDir, { recursive: true });
        }
        if (!await existsAsync(thumbnailDir)) {
            await mkdirAsync(thumbnailDir, { recursive: true });
        }

        // 3. 处理文件（兼容单文件/多文件上传）
        const fileField = Object.keys(ctx.request.files)[0];
        let files = Array.isArray(ctx.request.files[fileField])
            ? ctx.request.files[fileField]
            : [ctx.request.files[fileField]];

        // 4. 检查文件大小限制
        const totalSize = files.reduce((sum, f) => sum + f.size, 0);
        if (totalSize > MAX_TOTAL_SIZE) {
            ctx.status = 413;
            ctx.body = {
                code: 413,
                message: `总文件大小超过限制（最大${MAX_TOTAL_SIZE / 1024 / 1024}MB）`
            };
            return;
        }

        // 5. 并行处理每个文件
        const fileRecords = await Promise.all(files.map(async (file) => {
            // 检查单个文件大小
            if (file.size > MAX_FILE_SIZE) {
                throw new Error(`文件 ${file.originalFilename || file.name} 超过单个文件大小限制（最大${MAX_FILE_SIZE / 1024 / 1024}MB）`);
            }

            // 5.1 生成文件信息
            const fileId = uuidv4();
            const originalName = file.originalFilename || file.name;
            const fileExt = path.extname(originalName).toLowerCase();
            const fileName = `${fileId}${fileExt}`;
            const relativePath = path.join('uploads', dateFolder, fileName).replace(/\\/g, '/');
            const absolutePath = path.join(__dirname, '..', relativePath);
            const thumbnailPath = path.join(thumbnailDir, fileName);

            // 5.2 移动文件
            await renameAsync(file.filepath, absolutePath);

            // 5.3 如果是图片，生成缩略图
            const mimeType = file.mimetype || mime.lookup(fileExt) || 'application/octet-stream';
            let thumbnailGenerated = false;

            if (mimeType.startsWith('image/')) {
                thumbnailGenerated = await generateThumbnail(absolutePath, thumbnailPath);
            }

            // 5.4 构建完整数据库记录
            const fileRecord = {
                id: fileId,
                user_id: userid,
                filename: originalName,
                path: relativePath,
                size: file.size,
                mime_type: mimeType,
                file_ext: fileExt.replace('.', ''),
                created_at: now,
                status: 1,
                description: description || null,
                download_count: 0
            };

            // 5.5 写入数据库
            await db.query(
                `INSERT INTO upload SET ?`,
                [fileRecord]
            );

            return {
                ...fileRecord,
                created_at: now.toISOString(),
                url: `/file/${fileId}`,
                thumbnail: thumbnailGenerated
                    ? `/thumbnails/${dateFolder}/${fileName}`
                    : null
            };
        }));

        // 6. 返回结果
        ctx.body = {
            code: 200,
            message: `成功上传 ${fileRecords.length} 个文件`,
            data: {
                files: fileRecords,
                totalSize: fileRecords.reduce((sum, f) => sum + f.size, 0)
            }
        };

    } catch (error) {
        console.error('[文件上传错误]', error);

        // 7. 错误处理（区分不同错误类型）
        let statusCode = 500;
        let errorMessage = '文件处理失败';

        if (error.message.includes('超过单个文件大小限制')) {
            statusCode = 413;
            errorMessage = error.message;
        } else if (error.code && error.code.startsWith('ER_')) {
            statusCode = 502;
            errorMessage = '数据库写入失败';
        }

        ctx.status = statusCode;
        ctx.body = {
            code: statusCode,
            message: errorMessage,
            detail: process.env.NODE_ENV === 'development'
                ? { error: error.message, stack: error.stack }
                : null
        };
    }
};
/** 通过id访问文件 */
const getFileById = async (ctx, next) => {
    try {
        // 1. 从数据库获取文件信息
        let [file] = await db.query(
            'SELECT * FROM upload WHERE id = ?',
            [ctx.params.id]
        );

        if (!file) {
            ctx.status = 404;
            ctx.body = { code: 404, message: '文件不存在' };
            return;
        }

        // 2. 验证权限（如果需要）
        // if (file.user_id !== ctx.state.user.id) {
        //   ctx.status = 403;
        //   return;
        // }

        // 3. 构建文件路径
        file = file[0]
        const filePath = path.join(__dirname, '../', file.path); // 注意路径层级调整
        // 4. 检查文件是否存在
        if (!fs.existsSync(filePath)) {
            ctx.status = 404;
            ctx.body = { code: 404, message: '文件不存在' };
            return;
        }

        // 5. 设置响应头
        ctx.set('Content-Type', file.mime_type);
        ctx.set('Content-Disposition', `inline; filename="${file.filename}"`);

        // 6. 返回文件流
        ctx.body = fs.createReadStream(filePath);

        // 7. 更新下载计数（可选）
        await db.query(
            'UPDATE upload SET download_count = download_count + 1 WHERE id = ?',
            [file.id]
        );
    } catch (error) {
        console.error('文件访问错误:', error);
        ctx.status = 500;
        ctx.body = { code: 500, message: '文件访问失败' };
    }
}
/**
 * 获取文件列表（支持所有参数可选）
 * @param {Object} ctx - Koa上下文
 */
const getFileList = async (ctx) => {
    try {
        console.log(ctx.request.body)
        // 1. 解析查询参数
        const {
            file_ext,       // 文件扩展名
            user_id,        // 用户ID
            startTime,      // 开始时间
            endTime,        // 结束时间
            file_name,      // 文件名（模糊搜索）
            page = 1,       // 页码，默认为1
            pageSize = 10,  // 每页数量，默认为10
            status = 1,         // 文件状态
            orderBy = 'created_at', // 排序字段
            order = 'DESC'  // 排序方式
        } = ctx.request.body;
        // 2. 计算分页偏移量
        const offset = (page - 1) * pageSize;
        // 3. 构建基础SQL和参数
        let sql = 'SELECT * FROM upload WHERE 1=1';
        const params = [];
        // 4. 动态添加查询条件
        if (file_ext) {
            if (file_ext != '') {
                sql += ' AND file_ext = ?';
                params.push(file_ext);
            }
        }
        if (user_id) {
            if (user_id != '') {
                sql += ' AND user_id = ?';
                params.push(user_id);
            }
        }
        if (startTime) {
            if (startTime != '') {
                sql += ' AND created_at >= ?';
                params.push(startTime);
            }
        }
        if (endTime) {
            if (endTime != '') {
                sql += ' AND created_at <= ?';
                params.push(endTime);
            }
        }
        if (file_name) {
            if (file_name != '') {
                sql += ' AND filename LIKE ?';
                params.push(`%${file_name}%`);
            }
        }
        if (status) {
            if (status != '') {
                sql += ' AND status = ?';
                params.push(status);
            }
        }
        // 5. 添加排序和分页
        sql += ` ORDER BY ${orderBy} ${order} LIMIT ?, ?`;
        params.push(offset, parseInt(pageSize));

        // 6. 执行查询
        const files = await db.query(sql, params);

        // 7. 获取总数（用于分页信息）
        let countSql = 'SELECT COUNT(*) as total FROM upload WHERE 1=1';
        const countParams = [...params.slice(0, -2)]; // 去掉LIMIT的参数

        const [totalResult] = await db.query(countSql, countParams);
        const total = totalResult[0].total;

        // 8. 返回结果
        ctx.body = {
            code: 200,
            message: '获取文件列表成功',
            data: {
                list: files[0],
                pagination: {
                    current: parseInt(page),
                    pageSize: parseInt(pageSize),
                    total: total,
                    totalPages: Math.ceil(total / pageSize)
                }
            }
        };

    } catch (error) {
        console.error('获取文件列表错误:', error);
        ctx.status = 500;
        ctx.body = {
            code: 500,
            message: '获取文件列表失败',
            detail: process.env.NODE_ENV === 'development' ? error.message : null
        };
    }
};
/** 删除文件 */
const deleteFile = async (ctx) => {
    try {
        const { id, permanentlyDelete } = ctx.request.body;
        // 1. 查询文件信息
        const file = await db.query('SELECT * FROM upload WHERE id = ?', [id]);
        if (!file || file.length === 0) {
            ctx.status = 404;
            ctx.body = { code: 404, message: '文件不存在' };
            return;
        }
        // 2. 逻辑删除文件
        await db.query('UPDATE upload SET status = 0 WHERE id = ?', [id]);
        if (permanentlyDelete) {
            // 3. 删除文件
            const filePath = path.join(__dirname, 'uploads', file[0].file_path);
            fs.unlinkSync(filePath);
        }
        ctx.body = { code: 200, message: '删除文件成功' };
    } catch (error) {
        ctx.status = 500;
        ctx.body = { code: 500, message: '删除文件失败', error };
    }

}
module.exports = { uploadFile, getFileById, getFileList, deleteFile };